package ycl.important.common.utils;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.NumberUtil;
import com.google.common.collect.Maps;
import ycl.important.common.enums.NumMultiplyEnum;

import java.math.BigDecimal;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

/**
 * 金额计算工具
 *
 * @author: YCL
 * @date: 2021-09-03 16:14:10
 */
@SuppressWarnings("all")
public class BigDecimalUtil {

	private static final BigDecimal ZERO = BigDecimal.ZERO;
	private static final String NEGATIVE = "负";
	private static final String STRING_ZERO_CN = "零";
	private static final String STRING_ZERO_NUM = "0";
	private static final String[] UNIT = {"圆", "萬", "亿"};
	private static final String[] TEN_HUN_THO = {"拾", "佰", "仟"};

	/**
	 * 获取集合的总和
	 *
	 * @param c 集合
	 * @return 总和
	 */
	public static BigDecimal getSum(Collection<BigDecimal> c) {
		BigDecimal total = ZERO;
		if (CollUtil.isEmpty(c))
			return total;

		for (BigDecimal e : c)
			total = NumberUtil.add(total, e);

		return total;
	}


	/**
	 * 获取值的总和
	 *
	 * @param map value是BigDecimal类型的map集合
	 * @return value的总和
	 */
	public static BigDecimal getSum(Map<?, BigDecimal> map) {
		return getSum(map.values());
	}


	/**
	 * 获取 map 集合中包含着的某些键的值之和
	 *
	 * @param keys map的某些key
	 * @param map  值为BigDecimal的集合
	 * @param <K>  任意类型
	 * @return map里这些key的值的总和
	 */
	public static <K> BigDecimal getSumForKeys(Collection<K> keys, Map<K, BigDecimal> map) {
		BigDecimal total = ZERO;
		if (CollUtil.isEmpty(keys) || CollUtil.isEmpty(map))
			return total;

		for (K k : keys) {
			BigDecimal v = map.get(k);
			if (v == null)
				continue;
			total = NumberUtil.add(total, v);
		}
		return total;
	}


	/**
	 * 同键的两个 map 集合的值相加
	 *
	 * @param change 要改变的集合
	 * @param params 参照集合
	 * @param <K>    任意类, 两个集合的类型要一样
	 * @return 返回改变的集合
	 */
	public static <K> Map<K, BigDecimal> eqKeyChangeAdd(Map<K, BigDecimal> change, Map<K, BigDecimal> params) {
		return eqKeyChange(change, params, true);
	}


	/**
	 * 同键的两个 map 集合的值相减
	 *
	 * @param change 要改变的集合
	 * @param params 参照集合
	 * @param <K>    任意类, 两个集合的类型要一样
	 * @return 返回改变的集合
	 */
	public static <K> Map<K, BigDecimal> eqKeyChangeEven(Map<K, BigDecimal> change, Map<K, BigDecimal> params) {
		return eqKeyChange(change, params, false);
	}

	private static <K> Map<K, BigDecimal> eqKeyChange(Map<K, BigDecimal> change, Map<K, BigDecimal> params, boolean add) {
		if (CollUtil.isEmpty(change))
			return params;
		if (CollUtil.isEmpty(params))
			return Maps.newHashMap();

		change.forEach((k, v) -> {
			BigDecimal p = params.get(k);
			if (p == null || p.compareTo(ZERO) == 0)
				return;
			BigDecimal r = add ? NumberUtil.add(p, v) : NumberUtil.sub(p, v);
			params.put(k, r);
		});
		return params;
	}


	/**
	 * 金额分摊
	 *
	 * @param share 要分摊的金额
	 * @param total 总金额
	 * @param map   比例分配
	 * @param <K>   任意类型
	 * @return 每个key要分摊的金额
	 */
	public static <K> Map<K, BigDecimal> priceShare(BigDecimal share, BigDecimal total, Map<K, BigDecimal> map) {
		HashMap<K, BigDecimal> res = Maps.newHashMap();
		if (CollUtil.isEmpty(map))
			return res;

		BigDecimal min = new BigDecimal("0.01");
		BigDecimal base = NumberUtil.div(share, total, 2);
		BigDecimal last = share;
		int size = map.size(), count = 0;

		for (K k : map.keySet()) {
			//最后一个
			if (count == size - 1) {
				res.put(k, last);
				break;
			}

			BigDecimal v = map.get(k);
			if (v == null || v.compareTo(ZERO) == 0)
				continue;

			BigDecimal m = NumberUtil.mul(base, v);//这个元素的分摊金额
			if (m.compareTo(min) < 0)
				continue;

			res.put(k, m);
			last = NumberUtil.sub(last, m);
			count++;
		}
		return res;
	}


	/**
	 * 获取数值的大写
	 *
	 * @param num 金额数值
	 * @return 金额的大写
	 */
	@Deprecated
	public static String getMultiply(BigDecimal num) {
		if (num == null || num.compareTo(ZERO) == 0)
			return "零圆整";

		StringBuilder builder = new StringBuilder();
		if (num.compareTo(ZERO) < 0)
			builder.append(NEGATIVE);

		//防止出现逗号
		String[] s = num.toString().replaceAll(",", "")
				.split("\\.");
		String[] yuan = s[0].split("");

		int count = 0;
		boolean buildZero = false;
		//从右往左数
		for (int i = yuan.length - 1; i >= 0; i--) {
			StringBuilder b = new StringBuilder();
			int n = Integer.parseInt(yuan[i]);
			//如果当前的位置的数字是0
			if (n == 0) {
				//元、万、亿单位
				if (count % 4 == 0) {
					b.append(UNIT[count / 4]);
					buildZero = true;
				}
				if (buildZero) {
					b.append(STRING_ZERO_CN);
					buildZero = false;
				}

				//拼接上后: ??元 / ??万 / ??亿
				builder = lPush(builder, b);
				count++;
				continue;
			}
			String s1 = NumMultiplyEnum.getByNum(n);
			b.append(s1);
			int unit = count % 4;
			if (unit == 0)
				b.append(UNIT[count / 4]);
			else if (unit == 1)
				b.append("拾");
			else if (unit == 2)
				b.append("佰");
			else
				b.append("仟");
			builder = lPush(builder, b);
			count++;
		}

		if (s.length == 1)
			builder.append("整");
		else {
			String[] c = s[1].split("");
			int len = c.length;
			if (len == 1)
				builder.append(NumMultiplyEnum.getByNum(Integer.parseInt(c[0]))).append("角零分");
			else if (len == 2)
				builder.append(NumMultiplyEnum.getByNum(Integer.parseInt(c[0]))).append("角")
						.append(NumMultiplyEnum.getByNum(Integer.parseInt(c[1]))).append("分");
			else
				throw new IllegalArgumentException("金额精确到分");
		}
		return builder.toString();
	}

	/**
	 * 左边拼接
	 *
	 * @param target 目标 -> aaa
	 * @param s      要拼接的数据 -> bbb
	 * @return 拼接后的数据 -> bbbaaa
	 */
	private static StringBuilder lPush(StringBuilder target, StringBuilder s) {
		return s.append(target);
	}

	/**
	 * 右边拼接
	 *
	 * @param target 目标 -> aaa
	 * @param s      要拼接的数据 -> bbb
	 * @return 拼接后的数据 -> aaabbb
	 */
	private static StringBuilder rPush(StringBuilder target, StringBuilder s) {
		return target.append(s);
	}

	public static void main(String[] args) {
		String s = getMultiply(new BigDecimal("101010101.12"));
		System.out.println(s);
	}

//	public static String getMultiply2(BigDecimal num) {
//		if (num == null || num.compareTo(ZERO) == 0)
//			return "零圆整";
//
//		StringBuilder builder = new StringBuilder();
//		if (num.compareTo(ZERO) < 0)
//			builder.append(NEGATIVE);
//
//		//防止出现逗号
//		String[] s = num.toString().replaceAll(",", "")
//				.split("\\.");
//		String[] yuan = s[0].split("");//整数
//
//		boolean buildZero = false;
//		int count = yuan.length;
//		int index = 0;
//		for (String y : yuan) {
//			count--;
//			index++;
//			int m = count % 4;//取模
//			if (StrUtil.isNotBlank(builder)) {
//				if (m == 0) {
//					builder.append(UNIT[count / 4]);
//					continue;
//				}
//			}
//
//			if (y.equals(STRING_ZERO_NUM)) {
//				//判断从当前位到个位的全部是否为0
//				if (buildZero) {
//					boolean build = false;
//					for (int i = index; i < yuan.length; i++) {
//						if (! yuan[i].equals(STRING_ZERO_NUM)) {
//							build = true;
//							break;
//						}
//					}
//					if (build)
//						builder.append(STRING_ZERO_CN);
//					else {
//						builder.append(UNIT[0]);
//						break;
//					}
//				}
//				buildZero = false;
//				continue;
//			}
//
//			String multiply = NumMultiplyEnum.getByNum(Integer.parseInt(y));
//			builder.append(multiply);
//			if (m == 0)
//				builder.append(UNIT[count / 4]);
//			else
//				builder.append(TEN_HUN_THO[m - 1]);
//			buildZero = true;
//		}
//
//		//小数位
//		if (s.length == 1)
//			builder.append("整");
//		else {
//			String[] c = s[1].split("");
//			int len = c.length;
//			if (len == 1)
//				builder.append(NumMultiplyEnum.getByNum(Integer.parseInt(c[0]))).append("角零分");
//			else if (len == 2)
//				builder.append(NumMultiplyEnum.getByNum(Integer.parseInt(c[0]))).append("角")
//						.append(NumMultiplyEnum.getByNum(Integer.parseInt(c[1]))).append("分");
//			else
//				throw new IllegalArgumentException("金额精确到分");
//		}
//		return builder.toString();
//	}
//
//	public static String getMultiply3(BigDecimal num) {
//		if (num == null || num.compareTo(ZERO) == 0)
//			return "零圆整";
//
//		StringBuilder builder = new StringBuilder();
//		if (num.compareTo(ZERO) < 0)
//			builder.append(NEGATIVE);
//
//		//防止出现逗号
//		String[] money = num.toString().replaceAll(",", "")
//				.split("\\.");
//		String[] yuan = money[0].split("");//整数
//
//		List<List<String>> unit = new ArrayList<>();
//		int tempIndex = 0;
//		int tempCount = 0;
//		for (int i = yuan.length - 1; i >= 0; i--) {
//			List<String> list = new ArrayList<>();
//			if (tempCount == 0)
//				unit.add(list);
//			else
//				list = unit.get(tempIndex);
//
//			list.add(yuan[i]);
//			unit.set(tempIndex, list);
//			if (++ tempCount == 4) {
//				tempIndex++;
//				tempCount = 0;
//			}
//		}
//
//		//unit.forEach(Collections::reverse);
//
//
//		return null;
//	}
//
//
//	//1234
//	private static StringBuilder a(List<String> list, String unit) {
//		StringBuilder builder = new StringBuilder();
//		int index = 0;
//		for (String s : list) {
//			index++;
//			if (s.equals(STRING_ZERO_NUM)) {
//				boolean buildZero = false;
//				for (int i = index; i < list.size(); i++) {
//					if (! list.get(i).equals(STRING_ZERO_NUM)) {
//						buildZero = true;
//						break;
//					}
//				}
//				if (buildZero) {
//					builder = lPush(builder, new StringBuilder(STRING_ZERO_CN));
//				}
//			}
//			NumMultiplyEnum.getByNum()
//		}
//		return builder;
//	}
}
